/**
 * ThreadedWriter.java
 *
 * Enterprise Java
 *
 * Author:  Matthew Braddy
 * Created: Oct 19, 2010
 *
 */

package java113.project.threads;

import java.io.*;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java113.project.util.DocVsSecurityException;

/**
 *
 * @author Matthew Braddy
 */
public class ThreadedWriter implements Runnable {

    private Properties properties;

    private Map ledger;
    
    private Logger logger;

    // a boolean used to stop the thread
    private boolean      stopping;

    /**
     *
     * @param processOrder
     * @param properties
     */
    public ThreadedWriter(Map ledger, Properties properties) {

        super();

        setProperties(properties);

        logger = Logger.getLogger(this.properties.getProperty("logger"));

        setLedger(ledger);

    }

    /**
     *
     * @return
     */
    public Properties getProperties() {

        return this.properties;

    }

    /**
     *
     * @param properties
     */
    public void setProperties(Properties properties) {

        this.properties = properties;

    }

    /**
     *
     * @return
     */
    public Map getLedger() {

        return this.ledger;
        
    }
    
    /**
     *
     * @param processOrder
     */
    public void setLedger(Map ledger) {

        this.ledger = ledger;

    }

    


    /**
     *
     */
    public void run() {
        
        try {
        
            write();

        } catch (DocVsSecurityException ex) {

            Logger.getLogger(ThreadedWriter.class.getName()).log(Level.SEVERE, null, ex);

        }

    }

    /**
     *
     * @throws DocVsSecurityException
     */
    public void write() throws DocVsSecurityException {

        int counter = 0;

        BufferedWriter out = null;        

        String outputFilePath = properties.getProperty("path.output") +
                properties.getProperty("flat.file.output");

        while (!stopping) {

             if (ledger != null) {
                
                if (ledger.size() > counter) {

                    try {

                        if (counter == 0) {
                            
                            out = new BufferedWriter(
                                new FileWriter(outputFilePath, false));

                            logger.log(Level.INFO,
                                    outputFilePath + " has been created.");
                            
                        } else {
                            
                            out = new BufferedWriter(
                                new FileWriter(outputFilePath, true));
                            
                        }
                        
                        if ((outputFilePath == null) ||
                                (outputFilePath.length() == 0)) {
                            throw new DocVsSecurityException(
                                    "Path cannot be empty",
                                    DocVsSecurityException.INPUT_FAIL,
                                    "outputFilePath", outputFilePath);

                        } else if (outputFilePath.length() > 512) {
                            throw new DocVsSecurityException(
                                    "Path cannot exceed 512 characters",
                                    DocVsSecurityException.INPUT_FAIL,
                                    "outputFilePath", outputFilePath);

                        } else if (outputFilePath.indexOf(' ') >= 0) {
                            throw new DocVsSecurityException(
                                    "Path cannot contain spaces",
                                    DocVsSecurityException.INPUT_FAIL,
                                    "outputFilePath", outputFilePath);

                        }                        
                        
                        Object order = ledger.get(counter);

                        String output = order.toString();
                        
                        out.write(output);

                        logger.log(Level.INFO,
                                "A line has been written to the output file.");
                        
                        if ((output == null) || (output.length() == 0)) {
                            throw new DocVsSecurityException(
                                    "File contents cannot be empty", 
                                    DocVsSecurityException.OUTPUT_FAIL, 
                                    "strIn", out);
                            
                        } else if (output.length() > 1000000000) {
                            throw new DocVsSecurityException(
                                    "File should not exceed 1Gb in size", 
                                    DocVsSecurityException.OUTPUT_FAIL, 
                                    "strIn.length()", output.length());
                            
                        }   

                    } catch (FileNotFoundException fne) {

                        logger.log(Level.SEVERE,
                                "Encountered an exception: " + fne.getMessage());

                        fne.printStackTrace();

                    } catch (IOException ioe) {

                        logger.log(Level.SEVERE,
                                "Encountered an exception: " + ioe.getMessage());

                        ioe.printStackTrace();

                    } catch (Exception e) {

                        logger.log(Level.SEVERE,
                                "Encountered an exception: " + e.getMessage());

                        e.printStackTrace();

                    } finally {

                        try {

                            out.close();

                        } catch (Exception e) {

                            logger.log(Level.SEVERE,
                                "Encountered an exception: " + e.getMessage());

                            e.printStackTrace();

                        }

                    }

                    counter++;

                }

            }

             try {

                Thread.sleep(250);

            } catch (InterruptedException ex) {

                logger.log(Level.SEVERE, null, ex);

            }

        }

    }

    /**
     * 
     */
    public synchronized void allStop() {

        logger.log(Level.WARNING, "The ThreadedWriter's allStop()" +
                "has been called.");

        this.stopping = true;

    }

    /**
     *
     * @return
     */
    @Override
    public String toString() {

        StringBuffer strbHold;

        strbHold = new StringBuffer();
        strbHold.append("Properties file: " + this.properties.toString());
        strbHold.append(System.getProperty("line.separator"));
        strbHold.append("ProcessOrder: " + this.ledger.toString());
        return strbHold.toString ();

    }

}
